package XML;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import DTO.Field;
import DTO.ForeignKey;
import DTO.Row;
import DTO.Table;
import Main.DataType;

public class XMLHelper { 
	
	/**
	 * @param dbName	: database's name
	 * @return			: return result
	 */
	public static boolean CreateDatabase(String dbName)
	{
		File dir = new File("Database\\" + dbName);
			if(dir.exists()) return false;
		return dir.mkdir(); 
	}
	
	public static boolean DropDatabase(String dbName)
	{
		File dir =new File("Database\\"+dbName);
		if(!dir.exists()){
			System.out.println("Ko ton tai");
			return false;
		}
		return dir.delete();
	}
	
	public static boolean RenameDatabase(String sourceName, String targetName)
	{
		File dir =new File("Database\\"+sourceName);
		File target = new File("Database\\"+targetName); 
		if(!dir.exists() || target.exists()) return false;
		return dir.renameTo(target);
	}
	
	public static boolean CreateTableStructure(String dbName, String tableName, Vector<Field> fields)
	{
		boolean res = false;
		tableName = tableName.toLowerCase();
		if(!IsExist(dbName)) return res;
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder;
		try {
			docBuilder = docFactory.newDocumentBuilder();
			 
			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement(tableName);
			doc.appendChild(rootElement);
			
			int n = fields.size();
			for(int i =0; i < n; i++)
			{
				// Field elements
				Element field = doc.createElement("Field");
				rootElement.appendChild(field);
				
				field.setAttribute("ID", Integer.toString(i));
				
				// Name elements
				Element name = doc.createElement("Name");
				name.appendChild(doc.createTextNode(fields.get(i).get_Name()));
				field.appendChild(name);
				
				//NotNull element
				Element notNull = doc.createElement("NotNull");
				String notnull  = new Boolean(fields.get(i).is_NotNull()).toString();
				notNull.appendChild(doc.createTextNode(notnull));
				field.appendChild(notNull);
				
				//Type element
				Element type = doc.createElement("Type");
				String t = String.valueOf(fields.get(i).get_Type());
				type.appendChild(doc.createTextNode(t));
				field.appendChild(type);
				
				//Primary element
				Element isPrimaryKey = doc.createElement("IsPrimaryKey");
				String isPriKey  = new Boolean(fields.get(i).is_IsPrimaryKey()).toString();
				isPrimaryKey.appendChild(doc.createTextNode(isPriKey));
				field.appendChild(isPrimaryKey);
				
				//ForeignKey element
				Element foreignKey = doc.createElement("ForeignKey");
				
				String srcField = fields.get(i).get_ForeignKey().getSourceField();
				String targetField = fields.get(i).get_ForeignKey().getTargetField();
				String tb = fields.get(i).get_ForeignKey().getTargetTable();
				
				foreignKey.setAttribute("SourceField", srcField);
				foreignKey.setAttribute("TargetField", targetField);
				foreignKey.setAttribute("TargetTable", tb);
				
				field.appendChild(foreignKey);
			}
		
//			// write the content into xml file
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(new File("Database\\" + dbName +"\\" + tableName+ ".xml"));
	
			transformer.transform(source, result);
			res = true;
			return res;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return res;
			
		}
	
		
	}
	public static boolean CreateTableData(String dbName, String tbName, Vector<Row> rows)
	{
		boolean res = false;
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName)) return res;
		DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder;
		try {
			docBuilder = docFactory.newDocumentBuilder();
			 
			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement(dbName);
			doc.appendChild(rootElement);
			
			int n = rows.size();
			for(int i =0; i < n; i++)
			{
				// root elements
				Element row = doc.createElement(tbName);
				rootElement.appendChild(row);
								
				Set s = rows.get(i).get_Fileds().entrySet();
				Iterator it = s.iterator();
				while(it.hasNext())
				{
					Map.Entry m = (Map.Entry)it.next();
					
					Field field = GetFieldByName(dbName, tbName, String.valueOf(m.getKey()));
					
					int type = field.get_Type();
					Element element = doc.createElement(field.get_Name());
					if(type == DataType.INT)
					{
						int value = (int) m.getValue();
						
						element.appendChild(doc.createTextNode(Integer.toString(value)));
					}
					else {
						String value = String.valueOf( m.getValue());
						
						element.appendChild(doc.createTextNode(value));
					}
								
					row.appendChild(element);
				}
				Element delNode = doc.createElement("Deleted");
				row.appendChild(delNode);
				delNode.appendChild(doc.createTextNode(new Boolean(false).toString()));
			}
		
//			// write the content into xml file
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(new File("Database\\" + dbName +"\\" + tbName+ "data.xml"));
			
			// Output to console for testing
			// StreamResult result = new StreamResult(System.out);
			 
			transformer.transform(source, result);
			res = true;
			return res;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		return res;
	}
	}
	
	public static boolean InsertField(String dbName, String tbName,Field field)
	{
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName)) return false;
		if(IsExist(dbName, tbName, field.get_Name())) return false;
		boolean res = false;
		File file = new File("Database\\" + dbName+"\\" + tbName+".xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				
				doc.getDocumentElement().normalize();
				Element root = doc.getDocumentElement();
					
				int n = GetListOfFieldName(dbName, tbName).size();
				Element newField = doc.createElement("Field");
				newField.setAttribute("ID", Integer.toString(n));
				root.appendChild(newField);	  
				
				// Name elements
				Element name = doc.createElement("Name");
				name.appendChild(doc.createTextNode(field.get_Name()));
				newField.appendChild(name);
				
				//NotNull element
				Element notNull = doc.createElement("NotNull");
				String notnull  = new Boolean(field.is_NotNull()).toString();
				notNull.appendChild(doc.createTextNode(notnull));
				newField.appendChild(notNull);
				
				//Type element
				Element type = doc.createElement("Type");
				String t = String.valueOf(field.get_Type());
				type.appendChild(doc.createTextNode(t));
				newField.appendChild(type);
				
				//Primary element
				Element isPrimaryKey = doc.createElement("IsPrimaryKey");
				String isPriKey  = new Boolean(field.is_IsPrimaryKey()).toString();
				isPrimaryKey.appendChild(doc.createTextNode(isPriKey));
				newField.appendChild(isPrimaryKey);
				
				//ForeignKey element
				Element foreignKey = doc.createElement("ForeignKey");
				
				String srcField = field.get_ForeignKey().getSourceField();
				String targetField = field.get_ForeignKey().getTargetField();
				String tb = field.get_ForeignKey().getTargetTable();
				
				foreignKey.setAttribute("SourceField", srcField);
				foreignKey.setAttribute("TargetField", targetField);
				foreignKey.setAttribute("TargetTable", tb);
				
				newField.appendChild(foreignKey);
				
				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);
				StreamResult result = new StreamResult(file);
				transformer.transform(source, result);
			
				File file1 = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
				if(file1.exists())
				{
					if(field.get_Type() == DataType.INT)
					{
						if( InsertFieldData(dbName, tbName + "data", field.get_Name(), Integer.toString(0)))
						res = true;
					}
					else
					{
						if( InsertFieldData(dbName, tbName + "data", field.get_Name(), ""))
							res = true;
					}
				}
				else res = true;
		    }catch(Exception ex)
		    {
		    	ex.printStackTrace();
		    	return res;
		    }
			return res;
		
	}
	
	public static boolean InsertFieldData(String dbName, String tbName, String field, String value)
	{
		boolean res = false;
		tbName = tbName.toLowerCase();
		File file = new File("Database\\" + dbName+"\\" + tbName+".xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				
				doc.getDocumentElement().normalize();
				Element root = doc.getDocumentElement();
								
				int index = tbName.lastIndexOf("data");
				String rowName = tbName.substring(0, index);

				NodeList lstNode = doc.getElementsByTagName(rowName);
				int n = lstNode.getLength();

				for(int i = 0; i <n; i++)
				{
					Node node = lstNode.item(i);
					
					Node newNode = doc.createElement(field);
					newNode.appendChild(doc.createTextNode(value));
					node.appendChild(newNode);
				}
				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);
				StreamResult result = new StreamResult(file);
				transformer.transform(source, result);
				
				return true;
				
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		    	return res;
		    }		
	}
	
	public static boolean DeleteField(String dbName, String tbName, String fieldName)
	{
		boolean res = false;
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName, fieldName)) return false;
		File file = new File("Database\\" + dbName+"\\" + tbName+".xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				
				Element root = doc.getDocumentElement();
				
				NodeList lstNode = doc.getElementsByTagName("Name");
				int n = lstNode.getLength();
				for(int i = 0; i <n; i++)
				{
					Node node = lstNode.item(i);
					
					String fieldName1 =node.getTextContent();
					if(fieldName.equals(fieldName1))
					{
						Node parentNode = node.getParentNode();
						root.removeChild(parentNode);
						
						TransformerFactory transformerFactory = TransformerFactory.newInstance();
						Transformer transformer = transformerFactory.newTransformer();
						DOMSource source = new DOMSource(doc);
						StreamResult result = new StreamResult(file);
						transformer.transform(source, result);		
					}
				}
				if(DeleteFieldData(dbName, tbName , fieldName))
					res = true;
				return res;
		    }
		    catch(Exception e)
		    {
		    	return res;
		    }
	}

	public static boolean DeleteFieldData(String dbName, String tbName, String field)
	{
		boolean res = false;

		tbName = tbName.toLowerCase();
		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");

		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				
				NodeList list = doc.getElementsByTagName(tbName);
				NodeList m = list.item(0).getChildNodes();
				int x = m.getLength();
				for(int i = 0; i < x; i++)
				{
					System.out.println(m.item(i).getNodeName());
					
				}
				NodeList lstNode = doc.getElementsByTagName(field);
				int n = lstNode.getLength();
				for(int i = 0; i <n; i++)
				{
					Node node = lstNode.item(i);					
					Node parentNode = node.getParentNode();					
					parentNode.removeChild(node);
				}
				
				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);
				StreamResult result = new StreamResult(file);
				transformer.transform(source, result);		
				
				res = true;
				return res;
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		    	return res;
		    }
	}
	
	public static boolean UpdateField(String dbName, String tbName, String fieldName )
	{
		
		boolean res = false;
		 return res;
	}
	
	public static Field getPrimaryKey(String dbName, String tbName)
	{
		tbName = tbName.toLowerCase();
		Field key = null;
		if(!IsExist(dbName, tbName)) return key;
		Vector<Field> fields = GetListOfField(dbName, tbName);
		int l = fields.size();
		
		for(int i = 0 ; i < l; i ++)
		{
			Field f = fields.get(i);
			if(f.is_IsPrimaryKey())
			{
				String name = f.get_Name();
				int type = f.get_Type();
				ForeignKey foreignKey = f.get_ForeignKey();
				boolean notNull = f.is_NotNull();
				boolean isPrimaryKey = f.is_IsPrimaryKey();
				key = new Field(name, notNull, type,  isPrimaryKey,foreignKey);
			}
			
		}
		return key;
	}
	
	public static Table GetTable(String dbName, String tbName)
	{
		tbName = tbName.toLowerCase();
		Vector<Field> fields = 	GetListOfField(dbName, tbName);
		Vector<Row> rows = GetListOfRow(dbName, tbName);

		if(fields == null && rows == null)
			return null;
		
		Table table = new Table(
				tbName, 
				dbName, 
				fields, 
				rows);
		
		return table;
	}
	
	public static Vector<String> GetListOfFieldName(String dbName, String tbName)
	{
		Vector<String> res = new Vector<String>();
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName)){
			res = null;
			return res;
		}
		
		File file = new File("Database\\" + dbName+"\\" + tbName+".xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
								
				NodeList lstNode = doc.getElementsByTagName("Name");
				
				int n = lstNode.getLength();
				
				for(int i = 0; i < n; i++)
				{
					res.add(lstNode.item(i).getTextContent());
				}
				return res;
		    }catch(Exception e)
		    {
		    	return null;
		    }
		
	}
	
	public static Field GetFieldByName(String dbName, String tbName, String fieldName)
	{
		tbName = tbName.toLowerCase();
		Vector<Field> fields = GetListOfField(dbName, tbName);
		
		if(fields != null)
		{
			for(int i = 0 ; i < fields.size(); i++)
			{
				if(fields.get(i).get_Name().equals(fieldName))
					return fields.get(i);
			}
		}
		
		return null;
		
	}
	
	public static Vector<Field> GetListOfField(String dbName, String tbName)
	{
		Vector<Field> fields = new Vector<Field>();
		tbName = tbName.toLowerCase();
		File file = new File("Database\\" + dbName+"\\" + tbName+".xml");
		if(!file.exists()){
			return null;
		}
		
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				
				NodeList lstName		 	 = doc.getElementsByTagName("Name");
				NodeList lstNotNull 		 = doc.getElementsByTagName("NotNull");
				NodeList lstType			 = doc.getElementsByTagName("Type");
				NodeList lstIsPrimaryKey	 = doc.getElementsByTagName("IsPrimaryKey");
				NodeList lstForeignKey		 = doc.getElementsByTagName("ForeignKey");
			
				int n = lstType.getLength();
				//System.out.println(n);
				for(int i =0; i < n; i++)
				{
					String name			 = lstName.item(i).getTextContent();
					Boolean notNull		 = Boolean.valueOf(lstNotNull.item(i).getTextContent());
					int type			 = Integer.parseInt(lstType.item(i).getTextContent());
					boolean isPrimaryKey = Boolean.valueOf(lstIsPrimaryKey.item(i).getTextContent());
					
					NamedNodeMap foreignKey		 = lstForeignKey.item(i).getAttributes();
					int m 						 = foreignKey.getLength();
					String srcField				 = null, targetField = null, targetTable = null;
					
					if(foreignKey != null && m > 0)
					{
						srcField 		 = foreignKey.item(0).getTextContent();
						targetField		 = foreignKey.item(1).getTextContent();
						targetTable		 = foreignKey.item(2).getTextContent();
					}
					
					ForeignKey key = new ForeignKey(targetTable, srcField, targetField);
					Field field = new Field(name, notNull, type, isPrimaryKey, key);
					fields.add(field);
				}
				return fields;
		    }catch(Exception e)
		    {
		    	e.printStackTrace();
		    	return null;
		    }
		
		
	}

	public static int GetTypeOfFeild(String dbName, String tbName, String fieldName)
	{
		int  res = -1;
		tbName = tbName.toLowerCase();
		Vector<Field> fields = GetListOfField(dbName, tbName);
		int n = fields.size();
		if(n == 0) return res;
		for(int i = 0 ; i < n; i ++)
		{
			Field field = fields.get(i);
			if(fieldName.endsWith(field.get_Name()))
			{
				int type = field.get_Type();
				if(type == 0) res = 0;
				else res =1;
			}
		}
		return res;
		
	}
	
	public static Vector<Row> GetDeletedRow(String dbName, String tbName)
	{
		tbName = tbName.toLowerCase();
		Vector<Row> rows = new Vector<Row>();
		if(!IsExist(dbName, tbName)){
			
			rows = null; return  rows;
		}
		Vector<Field> fields = GetListOfField(dbName, tbName);
		//if( fields != null) System.out.println(fields.size());
		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();

				Element rootElement = doc.getDocumentElement();
				NodeList nodes = doc.getElementsByTagName(tbName);
				
				int size = fields.size();
				Vector<NodeList> lstNodes = new Vector<NodeList>();
				for(int i = 0; i < size; i++)
				{
					NodeList lst = doc.getElementsByTagName(fields.get(i).get_Name());
					lstNodes.add(lst);
				}
				
				NodeList delList = doc.getElementsByTagName("Deleted");
				int n = nodes.getLength();
				
				for(int i = 0; i < n; i++)
				{
					Map<String, Object> values = new HashMap<String, Object>();
					for(int j = 0; j < size; j ++)
					{
						int type = fields.get(j).get_Type();
						Object val;
						if(type == 0)
						{
							String valStr = lstNodes.get(j).item(i).getTextContent();
							if(valStr.equals("null")) val = "null";
							else
								val = Integer.parseInt(lstNodes.get(j).item(i).getTextContent());
						}
						else{
							val = lstNodes.get(j).item(i).getTextContent();
						}
						values.put(fields.get(j).get_Name(), val);
					}
					if(Boolean.valueOf(delList.item(i).getTextContent()).booleanValue() == true)
					{
						Row row = new Row(values, true);
						rows.add(row);
					}	
				}
				return rows;
		    }catch(Exception e)
		    {
		    	e.printStackTrace();
		    	return null;
		    }
	}
	
	public static Vector<Row> GetListOfRow(String dbName, String tbName)
	{
		Vector<Row> rows = new Vector<Row>();
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName)){
			
			rows = null; return rows;
		}
		Vector<Field> fields = GetListOfField(dbName, tbName);
		//if( fields != null) System.out.println(fields.size());
		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();

				Element rootElement = doc.getDocumentElement();
				NodeList nodes = doc.getElementsByTagName(tbName);
				
				int size = fields.size();
				Vector<NodeList> lstNodes = new Vector<NodeList>();
				for(int i = 0; i < size; i++)
				{
					NodeList lst = doc.getElementsByTagName(fields.get(i).get_Name());
					lstNodes.add(lst);
				}
				
				NodeList delList = doc.getElementsByTagName("Deleted");
				int n = nodes.getLength();
				
				for(int i = 0; i < n; i++)
				{
					Map<String, Object> values = new HashMap<String,Object>();
					for(int j = 0; j < size; j ++)
					{
						int type = fields.get(j).get_Type();
						Object val;
						if(type == 0)
						{
							String valStr = lstNodes.get(j).item(i).getTextContent();
							if(valStr.equals("null")) val = "null";
							else
								val = Integer.parseInt(lstNodes.get(j).item(i).getTextContent());
						}
						else{
							val = lstNodes.get(j).item(i).getTextContent();
						}
						values.put(fields.get(j).get_Name(), val);
					}
					if(Boolean.valueOf(delList.item(i).getTextContent()).booleanValue() == false)
					{
						Row row = new Row(values, false);
						rows.add(row);
					}
					
				}
				return rows;
		    }catch(Exception e)
		    {
		    	e.printStackTrace();
		    	return null;
		    }
	}
	
	public static boolean IsExist(String dbname)
	{
		File file = new File("Database\\" + dbname);
		return file.exists();
	}
	
	public static boolean IsExist(String dbName,String tbname)
	{
		if(!IsExist(dbName)) return false;
		tbname = tbname.toLowerCase();
		File file = new File("Database\\" + dbName +"\\" + tbname + ".xml");
		return file.exists();
	}
	
	public static boolean IsExist(String dbName, String tbName, String field)
	{
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName))
			return false;
		Vector<String> fields = GetListOfFieldName(dbName, tbName);
		int n = fields.size();
		for(int i = 0; i <n; i++)
		{
			
			if(fields.get(i).equals(field))
				return true;
		}
		return false;
	}

	public static int IsExist(String dbName, String tbName, Row row)
	{
		int res = -1;
		tbName = tbName.toLowerCase();
		Vector<Row> rows = GetListOfRow(dbName, tbName);
		int n = rows.size();
		for(int i = 0; i < n; i ++)
		{
			Row r = rows.get(i);
			if(r.Compare(row))
			{
				res = i;
			}
		}
		
		return res;
	}
	
	
	public static int IsExist(String dbName, String tbname, Object primaryKeyValue)
	{
		int index = -1;
		tbname = tbname.toLowerCase();
		Vector<Row> rows = GetListOfRow(dbName, tbname);
		
		int n = rows.size();	
		Field key = getPrimaryKey(dbName, tbname);
		for(int i =0; i <n; i++)
		{
			Map<String, Object> map1 = rows.get(i).get_Fileds();
			
			Set set = map1.entrySet();
			Iterator iterator = set.iterator();
			while(iterator.hasNext())
			{
				Map.Entry m = (Map.Entry)iterator.next();
				String f = String.valueOf(m.getKey());
				Object val = m.getValue();
				if(f.equals(key.get_Name()) && (String.valueOf(val)).equals(String.valueOf(primaryKeyValue)))
				{
					return i;
				}
					
			}
		}
		return index;
	}
	
	public static boolean InsertRow(String dbName, String tbName, Row newRow)
	{
		boolean res = false;

		//System.out.println(tbName);
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName + "data")) {

			Vector<Row> rows = new Vector<Row>();
			rows.add(newRow);
			return CreateTableData(dbName, tbName, rows);		
		}
		
				
		//recovery row if it is deleted
		Vector<Row> delRows = GetDeletedRow(dbName, tbName);
		if(IsExist(delRows, newRow) >=0)
		{
			return RecoveryRow(dbName, tbName, newRow);
		}
		
		Vector<Field> fields = GetListOfField(dbName, tbName);	
		
		Object obj = null;
		Map<String, Object> map1 = newRow.get_Fileds();
		
		Set set = map1.entrySet();
		Iterator iterator = set.iterator();
		while(iterator.hasNext())
		{
			Map.Entry m = (Map.Entry)iterator.next();
			String f = String.valueOf(m.getKey());
			for(int i = 0 ; i < fields.size(); i++)
			{
				if(fields.get(i).is_IsPrimaryKey() &&
						fields.get(i).get_Name().equals(f))
				{
					obj = m.getValue();
					//System.out.println("Priamry key: " + f + " Value: "+ obj.toString());
				}
			}							
		}
		
		if(IsExist(dbName, tbName, obj)>0) return res;
		if(!IsExist(dbName, tbName) || (IsExist(dbName, tbName , newRow )>0)) return res;

		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");

		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				Element rootElement = doc.getDocumentElement();
				
				//Check is exist?
				Field primaryKey = getPrimaryKey(dbName, tbName);
				String keyName = primaryKey.get_Name();
				NodeList nodeList = doc.getElementsByTagName(keyName);
				
				int n = nodeList.getLength();
				System.out.println("So row: " + n);
				for(int i = 0; i<n; i++)
				{
					String str = String.valueOf(obj);
					Node node = nodeList.item(i);
					String nodeVal = node.getTextContent();
					if(str.equals(nodeVal)){
						//System.out.println("Priamry key: " + keyName + " Value: "+ obj.toString());
						System.out.println("Da ton tai: " + i);
						return false;
					}
				}
				
				
				Element row = doc.createElement(tbName);
				rootElement.appendChild(row);
								
				Set s1 = newRow.get_Fileds().entrySet();			
				Iterator it1 = s1.iterator();
				
				while(it1.hasNext())
				{
					Map.Entry m = (Map.Entry)it1.next();
										
					String field = String.valueOf(m.getKey());
					for(int i = 0 ; i < fields.size(); i++)
						if(fields.get(i).get_Name().equals(field))
						{
							int type = fields.get(i).get_Type();
							Element element = doc.createElement(field);
							row.appendChild(element);
							if(type == DataType.INT)
							{
								int value = 0;
								String valStr = String.valueOf(m.getValue());
								if(valStr == "null")
									element.appendChild(doc.createTextNode("null"));
								else{
									value = Integer.parseInt(String.valueOf(m.getValue()));
									element.appendChild(doc.createTextNode(Integer.toString(value)));
								}
								
							}
							else {
								String value = String.valueOf( m.getValue());
								
								element.appendChild(doc.createTextNode(value));
							}
						}					
				}
				Element delNode = doc.createElement("Deleted");
				row.appendChild(delNode);
				delNode.appendChild(doc.createTextNode(new Boolean(false).toString()));
				
//			// write the content into xml file
			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(new File("Database\\" + dbName +"\\" + tbName+ "data.xml"));
		
			transformer.transform(source, result);
			res = true;
			return res;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		return res;
				
		
		}
	}
	
	public static int IsExist(Vector<Row> rows, Row row)
	{
		int index = -1;
		int n = rows.size();
		if(n ==0 ) return index;
		for(int i = 0 ; i < n; i ++)
			if(rows.get(i).Compare(row))
			{
				return i;
			}
		return index;
	}
	
	public static boolean DeleteRow(String dbName, String tbName, Object primaryKey)
	{
		boolean res = false;
		
		if(!IsExist(dbName, tbName ))
		 return res;
		
		String keyName = getPrimaryKey(dbName, tbName).get_Name();
		
		
		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				Element rootElement = doc.getDocumentElement();
			
				NodeList lstNodes = doc.getElementsByTagName("Deleted");
				NodeList lstKey = doc.getElementsByTagName(keyName);
				int n = lstKey.getLength();
				int t = -1;
				for(int i = 0; i < n; i ++)
				{
					
				Node node = lstNodes.item(i);
				Node node1 = lstKey.item(i);
				if(node1.getTextContent().equals(primaryKey.toString()))
				{
					node.setTextContent(new Boolean(true).toString());
					t=i;
				}
				
				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);
				StreamResult result = new StreamResult(file);
				transformer.transform(source, result);
				}
				if(t >=0) res = true;
				
		    }
		    catch(Exception e)
		    {
		    	res = false;
		    }
		    return res;
	}
	
	public static boolean DeleteRow(String dbName, String tbName, Row row)
	{
		boolean res = false;
		tbName = tbName.toLowerCase();
		Vector<Row> rows = GetAllRows(dbName, tbName);
		System.out.println("So rows : " +rows.size());
		int index = IsExist(rows, row);
		System.out.println("Index: "+ index);
		if(index<0) return res;
		
		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				Element rootElement = doc.getDocumentElement();
			
				NodeList lstNodes = doc.getElementsByTagName("Deleted");
				Node node = lstNodes.item(index);
				node.setTextContent(new Boolean(true).toString());
				
				TransformerFactory transformerFactory = TransformerFactory.newInstance();
				Transformer transformer = transformerFactory.newTransformer();
				DOMSource source = new DOMSource(doc);
				StreamResult result = new StreamResult(file);
				transformer.transform(source, result);		
				res = true;
				return res;
		    }
		    catch(Exception e)
		    {
		    	return res;
		    }
	}
	
	public static Vector<Row> GetRows(String dbName, String tbName, String field)
	{
		Vector<Row> lstRow = new Vector<Row>();
		tbName = tbName.toLowerCase();
		
		Vector<Row> rows = GetListOfRow(dbName, tbName);
		int n = rows.size();
		
		for(int i = 0; i < n; i++)
		{
			Row r = rows.get(i);
			Map<String, Object> map = r.get_Fileds();
			Set s = map.entrySet();
			Iterator it = s.iterator();
			while(it.hasNext())
			{
				Map.Entry m = (Map.Entry) it.next();
				String fName = String.valueOf(m.getKey());
				
				Object val = m.getValue();
				//String strVal = (String)m.getValue();
				//if(strVal.equals("")) val = null;
				
				if(fName.equals(field))
				{
					Row newRow = new Row(map, false);
					lstRow.add(newRow);
				}	
			}
		}
		return lstRow;
	}
	
	public static Vector<Row> GetRows(String dbName, String tbName, String field, Object value)
	{
		Vector<Row> lstRow = new Vector<Row>();
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName + "data")) return lstRow;
		Vector<Row> rows = GetListOfRow(dbName, tbName);
		int n = rows.size();
		if(!IsExist(dbName, tbName, field)) return lstRow;
		for(int i = 0; i < n; i++)
		{
			Row r = rows.get(i);
			Map<String, Object> map = r.get_Fileds();
			Set s = map.entrySet();
			Iterator it = s.iterator();
			while(it.hasNext())
			{
				Map.Entry m = (Map.Entry) it.next();
				String f = String.valueOf(m.getKey());
				String fName = f;
				Object val = m.getValue();
				//String strVal = (String)m.getValue();
				//if(strVal.equals("")) val = null;
				
				if(fName.equals(field) && val.equals(value))
				{
					Row newRow = new Row(map, false);
					lstRow.add(newRow);
				}	
			}
		}
		return lstRow;
	}

	public static Vector<Row> GetRows(String dbName, String tbName, Vector<String> lstField, Vector<Object> lstVal)
	{
		tbName = tbName.toLowerCase();
		Vector<Vector<Row>> lstOfRows = new Vector<Vector<Row>>();
		
		Vector<Row> temp = new Vector<Row>();
		Vector<Row> rowsToUpdate = new Vector<Row>();
		int n = lstField.size();
		for(int i= 0; i <n; i++){
			if(!IsExist(dbName, tbName, lstField.get(i))) return
				rowsToUpdate;
			
		}
		for(int i =0; i < n; i++)
		{
			Vector<Row> rows = GetRows(dbName, tbName, lstField.get(i),lstVal.get(i));
			lstOfRows.add(rows);
		}
		
		int length = lstOfRows.size();
		for(int i = 0; i < length; i++)
		{
			Vector<Row> rows = lstOfRows.get(i);
			int size = rows.size();
			for(int j = 0; j < size; j++)
			{
				Row row = rows.get(j);
				temp.add(row);
			}
		}
		
		int nRows = temp.size();
		for(int i = 0; i<nRows; i++)
		{
			Row r = temp.get(i);
			int times = GetTimes(temp, r);
			int t = 0;
			if(n ==1) t = 0; else t = 1;
			if(times>t)
			{
				int index = IsExist(rowsToUpdate, r);
				if(index < 0)
					rowsToUpdate.add(r);
			}
		}
		
		return rowsToUpdate;
	}
	
	public static int GetTimes(Vector<Row> rows, Row row)
	{
		int times = 0;
		int n = rows.size();
		
		for(int i = 0; i < n; i ++)
		{
			Row r = rows.get(i);
			if(r.Compare(row))
				times++;
		}
		return times;
	}
	
	public static boolean RecoveryRow(String dbName, String tbName, Row row)
	{
		boolean res = false;
		if(!IsExist(dbName, tbName)) return res;
		tbName = tbName.toLowerCase();
		Vector<Row> rows = GetAllRows(dbName,  tbName);
		int index = IsExist(rows, row);
		System.out.println("Index:" +  index);
		if(index < 0) return res;
		else
		{

			File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
			DocumentBuilderFactory dbf;
			DocumentBuilder db;
			Document doc;
			    try
			    {
			    	dbf = DocumentBuilderFactory.newInstance();
					
					db = dbf.newDocumentBuilder();
					doc = db.parse(file);
					doc.getDocumentElement().normalize();
					Element rootElement = doc.getDocumentElement();
				
					NodeList lstNodes = doc.getElementsByTagName("Deleted");
					Node node = lstNodes.item(index);
					node.setTextContent(new Boolean(false).toString());
					
					TransformerFactory transformerFactory = TransformerFactory.newInstance();
					Transformer transformer = transformerFactory.newTransformer();
					DOMSource source = new DOMSource(doc);
					StreamResult result = new StreamResult(file);
					transformer.transform(source, result);		
					res = true;
					return res;
			    }
			    catch(Exception e)
			    {
			    	return res;
			    }
		}
	}

	public static Vector<Row> GetAllRows(String dbName, String tbName)
	{
		Vector<Row> rows = new Vector<Row>();
		tbName = tbName.toLowerCase();
		if(!IsExist(dbName, tbName)){
			
			rows = null; return rows;
		}
		Vector<Field> fields = GetListOfField(dbName, tbName);
		
		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
		System.out.println(file.exists());

		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();

				Element rootElement = doc.getDocumentElement();
				NodeList nodes = doc.getElementsByTagName(tbName);
				
				int size = fields.size();
				Vector<NodeList> lstNodes = new Vector<NodeList>();
				for(int i = 0; i < size; i++)
				{
					NodeList lst = doc.getElementsByTagName(fields.get(i).get_Name());
					lstNodes.add(lst);
				}
				
				NodeList delList = doc.getElementsByTagName("Deleted");
				int n = nodes.getLength();
				System.out.println(  delList.getLength() + " " + lstNodes.get(0).getLength() + " " + lstNodes.get(1).getLength() + "n = " + n);
				for(int i = 0; i < n; i++)
				{
					Map<String, Object> values = new HashMap<String, Object>();
					for(int j = 0; j < size; j ++)
					{
						int type = fields.get(j).get_Type();
						Object val;

						if(type == 0)
						{
							String valStr = lstNodes.get(j).item(i).getTextContent();
							if(valStr.equals("null")) val = "null";
							else
								val = Integer.parseInt(lstNodes.get(j).item(i).getTextContent());
						}
						else{
							
								val = lstNodes.get(j).item(i).getTextContent();
						}
						values.put(fields.get(j).get_Name(), val);
					}
					Row row = null;
					if(Boolean.valueOf(delList.item(i).getTextContent()).booleanValue() == false)
					{
						row = new Row(values, false);
						
					}
					else if(Boolean.valueOf(delList.item(i).getTextContent()).booleanValue() == true)
					{
						 row = new Row(values, true);
						
					}
					System.out.println("Add : " + rows.add(row));
				}
				return rows;
		    }catch(Exception e)
		    {
		    	e.printStackTrace();
		    	return null;
		    }
	}

	public static boolean UpdateRow(String dbName, String tbName,
			Vector<String> fieldUpdate, Vector<Object> valUpdate, Vector<Integer> valType,
			Vector<Row> rowUpdate)
	{
		boolean res = false;
		int t1 = fieldUpdate.size();
		for(int i =0; i<t1; i++)
		{
			if(!IsExist(dbName, tbName, fieldUpdate.get(i))) return res;
		}
		tbName = tbName.toLowerCase();
		if(!CheckFieldCondition(dbName, tbName, fieldUpdate)) return false;
		
		Vector<Row> rowsToUpdate = new Vector<Row>();
		rowsToUpdate = rowUpdate;
		if(rowsToUpdate.size() == 0)
			{
				System.out.println("Ko co row nao nhu vay");
				return res;
			}
		
		if(!CheckFieldTypeUpdate(dbName, tbName, fieldUpdate, valType)) return false;

		File file = new File("Database\\" + dbName+"\\" + tbName+"data.xml");
		DocumentBuilderFactory dbf;
		DocumentBuilder db;
		Document doc;
		    try
		    {
		    	dbf = DocumentBuilderFactory.newInstance();
				
				db = dbf.newDocumentBuilder();
				doc = db.parse(file);
				doc.getDocumentElement().normalize();
				Element rootElement = doc.getDocumentElement();
				
				Vector<Row> lstRow = GetListOfRow(dbName, tbName);

				System.out.println("aaaaa " + lstRow.size());
				int nRowsToUpdate = rowsToUpdate.size();
				int[] id = new int[nRowsToUpdate];
				for(int i = 0; i < nRowsToUpdate; i++)
				{
					Row r = rowsToUpdate.get(i);
					int sit = IsExist(lstRow, r);
					if(sit > 0) id[i] = sit;
				}
				
				Vector<NodeList> lstRowNodesToUpdate = new Vector<NodeList>();
				int nFieldsToUpdate = fieldUpdate.size();
				
				for(int i = 0; i < nFieldsToUpdate; i++)
				{
					if(!IsExist(dbName,tbName, fieldUpdate.get(i))) return  false;
					String field = fieldUpdate.get(i);
					NodeList lstNode = doc.getElementsByTagName(field);
					lstRowNodesToUpdate.add(lstNode);
				}
				
				for(int i = 0; i < nFieldsToUpdate; i++)
				{
					NodeList lstNode = lstRowNodesToUpdate.get(i);
					for(int j = 0; j < nRowsToUpdate; j++)
					{
						Node node = lstNode.item(id[j]);
						String val = valUpdate.get(i).toString();
						node.setTextContent(val);
						
						TransformerFactory transformerFactory = TransformerFactory.newInstance();
						Transformer transformer = transformerFactory.newTransformer();
						DOMSource source = new DOMSource(doc);
						StreamResult result = new StreamResult(file);
						transformer.transform(source, result);		
					}		
				}
				res = true;
				return res;
		    }
		    catch(Exception e)
		    {
		    	e.printStackTrace();
		    	return res;
		    }
	}

	private static boolean CheckFieldTypeUpdate(String dbName, String tbName,
			Vector<String> fieldUpdate, Vector<Integer> valType) {
		tbName = tbName.toLowerCase();
		int t = fieldUpdate.size();
		for(int i = 0; i < t; i++)
		{
			int type = GetTypeOfFeild(dbName, tbName, fieldUpdate.get(i));
			if(type <0 ) return false;
			if(type != valType.get(i))
			{
				return false;
			}
			
		}
		return true;
	}

	private static boolean CheckFieldCondition(String dbName, String tbName,
			Vector<String> fieldCondition) {
		tbName = tbName.toLowerCase();
		int t1 = fieldCondition.size();
		for(int i = 0; i<t1; i++)
		{
			if(!IsExist(dbName, tbName, fieldCondition.get(i))) return false;
		}
		return true;
	}
}

